/**
 * 
 */
package wong.board.client.ui;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import wong.board.client.ui.SearchPresenter.View;
import wong.board.client.widgets.Button;
import wong.board.client.widgets.Content;
import wong.board.client.widgets.ContentContainer;
import wong.board.client.widgets.ContentForm;
import wong.board.client.widgets.ContentPanel;
import wong.board.client.widgets.ElementPanel;
import wong.board.client.widgets.HasButtonCallbacks;
import wong.board.client.widgets.HasFormCallbacks;
import wong.board.client.widgets.IFrame;
import wong.board.client.widgets.Input;
import wong.board.client.widgets.Table;
import wong.board.client.widgets.ToggleButton;
import wong.board.shared.ContentKeys;

import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.impl.FocusImpl;

/**
 * @author wong
 * 
 */
public class SearchView extends ContentContainer implements View {
	private Input searchInput;
	private ContentPanel optionsPanel;
	//
	private HashMap<String, String> optionsMap;
	private UIHandler handler;
	//
	private ContentContainer resultPanel;
	private Table resultTable;
	private Button<String> resultCloseButton;
	private HandlerRegistration resizeRegistration;
	private ArrayList<String> engineNames;

	public SearchView() {
		super(ContentKeys.Search.toString());
		//
		searchInput = new Input();
		searchInput.addStyleName(boardCss.searchInput());
		searchInput.addStyleName(boardCss.searchItem());
		searchInput.setPlaceholder("search");

		optionsPanel = new ContentPanel();
		optionsPanel.addStyleName(boardCss.searchOptions());

		optionsMap = new HashMap<String, String>();

		getContent().add(optionsPanel);
		getContent().add(searchInput);

		addStyleName(boardCss.search());
	}

	@Override
	protected Content createContainer() {
		return new ContentForm();
	}

	@Override
	protected void onAttach() {
		super.onAttach();
		handler = new UIHandler();
		resizeRegistration = Window.addResizeHandler(handler);

		FocusImpl.getFocusImplForWidget().focus(searchInput.getElement());
	}

	@Override
	protected void onDetach() {
		resizeRegistration.removeHandler();
		handler = null;
		super.onDetach();
	}

	@Override
	public void resetView() {
		searchInput.setText("");
		optionsPanel.clear();
		optionsMap.clear();
	}

	@Override
	public void addEngine(String name, String query, boolean selected) {
		if (engineNames == null) {
			engineNames = new ArrayList<String>();
		}
		if (!engineNames.contains(name)) {
			engineNames.add(name);
			ToggleButton option = new ToggleButton(name);
			option.setTitle(query);
			option.addStyleName(boardCss.searchItem());
			option.addStyleName(boardCss.searchOption());
			option.setValue(Boolean.valueOf(selected));
			option.getElement().setId(name);
			optionsMap.put(name, query);
			optionsPanel.add(option);
		}
	}

	@Override
	public void showResults() {
		if (resultPanel == null) {
			resultCloseButton = getResultCloseButton();
			resultTable = new Table();
			resultTable.addStyleName(boardCss.searchResultFrames());
			resultPanel = new ContentContainer("Search Result");
			resultPanel.addStyleName(boardCss.searchResult());
			resultPanel.getContent().asWidget().addStyleName(boardCss.searchResultContent());
			resultPanel.getContent().add(resultTable);
			resultPanel.getContainer().add(resultCloseButton);
			resultPanel.setVisible(false);
			ElementPanel.create(this.getParent().getElement()).add(resultPanel);
		}
		String query = searchInput.getText();
		if (query.trim().length() > 0) {
			List<String> options = getSelectedOptions();
			if (options.size() > 0) {
				adjustResultPanel();
				resultTable.clear();
				resultPanel.setVisible(true);
				ArrayList<IsWidget> widgets = new ArrayList<IsWidget>();
				for (String option : options) {
					String optionUrl = optionsMap.get(option);
					optionUrl = optionUrl.replace("[q]", query);
					IFrame frame = new IFrame();
					frame.addStyleName(boardCss.searchResultFrame());
					ContentPanel wrapper = new ContentPanel();
					wrapper.addStyleName(boardCss.searchResultWrapper());
					wrapper.add(frame);
					widgets.add(wrapper);
					frame.setSrc(optionUrl);
				}
				resultTable.addRowData(widgets);
			}
		}
	}

	private Button<String> getResultCloseButton() {
		if (resultCloseButton == null) {
			resultCloseButton = new Button<String>(ID_CLOSE, "X");
			resultCloseButton.addStyleName(boardCss.searchResultCloseButton());
		}
		return resultCloseButton;
	}

	@Override
	public void hideResults() {
		if (resultPanel == null) {
			return;
		}
		resultPanel.setVisible(false);
	}

	@Override
	public void hideResultsOnEmptySearch() {
		if (searchInput.getText().trim().length() <= 0) {
			hideResults();
		}
	}

	@Override
	public HasFormCallbacks getFormCallbacks() {
		return (ContentForm) getContainer();
	}

	@Override
	public HasButtonCallbacks<String> getResultCloseButtonCallbacks() {
		return getResultCloseButton();
	}

	private void adjustResultPanel() {
		if (resultPanel == null) {
			return;
		}
		double y = this.getElement().getOffsetTop() + searchInput.getElement().getOffsetTop()
				+ searchInput.getElement().getOffsetHeight() + 11;
		resultPanel.getElement().getStyle().setTop(y, Unit.PX);

		double h = Window.getClientHeight() - y - 44;
		resultPanel.getElement().getStyle().setHeight(h, Unit.PX);
	}

	private List<String> getSelectedOptions() {
		ArrayList<String> names = new ArrayList<String>();
		int count = optionsPanel.getWidgetCount();
		for (int i = 0; i < count; i++) {
			Widget w = optionsPanel.getWidget(i);
			if (w instanceof ToggleButton) {
				if (((ToggleButton) w).getValue().booleanValue()) {
					names.add(w.getElement().getId());
				}
			}
		}
		return names;
	}

	private class UIHandler implements ResizeHandler {

		@Override
		public void onResize(ResizeEvent event) {
			adjustResultPanel();
		}

	}

}
